#ifndef _USAGE_H
#define _USAGE_H

#include <cstdlib>		//for atol(), needed by some machines.
#include <cstring>		// for strncmp(), strchr().
#include <sys/times.h>
#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;

#undef CKTCLK_TCK
#define CKTCLK_TCK sysconf(_SC_CLK_TCK)

class Usage
{
public:
  Usage ()
  {
    _initMem = check_mem ();
    _currentTick = check_tick ();
    _periodUsedTime = _totalUsedTime = 0.0;
  }

  void report ()
  {
    set_memUsage ();
    set_timeUsage ();
    /*
       cout << "Period time used : " << setprecision(4)
       << _periodUsedTime << " seconds" << endl;
       cout << "Total time used  : " << setprecision(4)
       << _totalUsedTime << " seconds" << endl;
       cout << "Total memory used: " << setprecision(4)
       << _currentMem << " M Bytes" << endl;
     */
    cout << "[ Usage Report ] ";
    cout << "Period [ " << setprecision (4) << _periodUsedTime << " s ]   ";
    cout << "Total  [ " << setprecision (4) << _totalUsedTime << " s ]   ";
    cout << "memory [ " << setprecision (4) << _currentMem << " M Bytes ]" <<
      endl;

  }

private:

  double check_mem () const
  {
    ifstream inf ("/proc/self/status");
    if (!inf)
      {
	cerr << "Cannot get memory usage" << endl;
	return 0.0;
      }
    const size_t bufSize = 128;
    char bufStr[bufSize];
    while (!inf.eof ())
      {
	inf.getline (bufStr, bufSize);
	if (strncmp (bufStr, "VmSize", 6) == 0)
	  {
	    long memSizeLong = atol (strchr (bufStr, ' '));
	    return (memSizeLong / 1024.0);
	  }
      }
    return 0.0;
  }
  double check_tick () const
  {
    tms tBuffer;
      times (&tBuffer);
      return tBuffer.tms_utime;
  }
  void set_memUsage ()
  {
    _currentMem = check_mem () - _initMem;
  }
  void set_timeUsage ()
  {
    double thisTick = check_tick ();
    _periodUsedTime = (thisTick - _currentTick) / (double) (CKTCLK_TCK);
    _totalUsedTime += _periodUsedTime;
    _currentTick = thisTick;
  }

  //For memory usage
  double _initMem;
  double _currentMem;

  //For CPU time usage
  double _currentTick;
  double _periodUsedTime;
  double _totalUsedTime;
};

#endif
